package auctionsimulation.market;

import java.util.HashMap;
import java.util.TimerTask;
import java.util.logging.Logger;

import auctionsimulation.agent.Agent;
import auctionsimulation.agent.BuyAgent;
import auctionsimulation.agent.SellAgent;
import auctionsimulation.statistics.Statistics;

public class DoubleAuction extends Auction {

	private static final long serialVersionUID = 2174077630022690347L;

	private long runtime;
	private double currentLowestPrice;
	private Agent currentLowestSeller;
	private double currentHighestBid;
	private Agent currentHighestBidder;

	public DoubleAuction(Agent initiator,
			HashMap<String, Long> productTemplate, double price, long runtime) {
		super(initiator, productTemplate);
		this.runtime = runtime;
		if (price <= 0)
			throw new IllegalAuctionException(
					"price of new double auction must be positive");
		if (runtime <= 0)
			throw new IllegalAuctionException(
					"runtime of new double auction must be positive");
		if (initiator instanceof SellAgent) {
			this.currentLowestSeller = initiator;
			this.currentLowestPrice = price;
		} else if (initiator instanceof BuyAgent) {
			this.currentHighestBidder = (BuyAgent) initiator;
			this.currentHighestBid = price;
		}
	}

	@Override
	public double getCurrentPrice() {
		return this.currentLowestPrice;
	}

	public synchronized boolean placePriceBid(Agent seller, double price,
			HashMap<String, Long> offeredTemplate) {
		if (started && !finished && price < currentLowestPrice && price > 0
				&& this.checkNewOfferTemplateBetter(offeredTemplate)) {
			currentLowestPrice = price;
			currentLowestSeller = seller;
			if(currentHighestBid >= currentLowestPrice) {
				this.finished = true;
				this.successfull = true;
				Statistics.successfullAuctions++;
				Statistics.successfullDoubleAuctions++;
				this.timer.cancel();
			}
			return true;
		}
		return false;
	}

	public synchronized boolean placeBid(Agent bidder, double price) {
		if (started && !finished && price > currentHighestBid) {
			currentHighestBid = price;
			currentHighestBidder = bidder;
			if(currentHighestBid >= currentLowestPrice) {
				this.finished = true;
				this.successfull = true;
				Statistics.successfullAuctions++;
				Statistics.successfullDoubleAuctions++;
				this.timer.cancel();
			}
			return true;
		}
		return false;
	}

	@Override
	public synchronized void start() {
		if (!started) {
			timer.schedule(new AuctionTask(), this.runtime);
			started = true;
			Statistics.startedAuctions++;
			Statistics.startedDoubleAuctions++;
			Logger.getGlobal().info("auction " + this + " has been started");
		}
	}

	private class AuctionTask extends TimerTask {

		@Override
		public void run() {
			if (!finished) {
				finished = true;
				Logger.getGlobal().info("auction " + this + "ended unsuccessfully.");
			}
		}
	}

}
